﻿#region Using Statements
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
#endregion

namespace StarFox.Screens
{
    /// <summary>
    /// Gameplay screen of the game.
    /// <para>Definition of Update() method.</para>
    /// </summary>
    partial class GamePlayScreen
    {
        #region Screen Transitions

        bool toVisible = false;
        float trTime = 0.0f;

        /// <summary>
        /// Makes the Screen transition to visible state.
        /// </summary>
        public override void Show()
        {
            toVisible = true;
            if (!Paused) { state = GAMESTATE.GAMESTART; LifeStart(); }
            base.Show();
        }

        /// <summary>
        /// Makes the Screen transition to hidden state.
        /// </summary>
        public override void Hide()
        {
            vibration.Pause();
            sound.PauseAllSounds();
            base.Hide();
        }

        #endregion

        #region Game States

        enum GAMESTATE { GAMESTART, GAMEPLAY, GAMEOVER }

        GAMESTATE state;

        private void LifeStart()
        {
            ship.Stop();
            hud.Visible = true;
            countDown.Start();
        }

        private void LifeLost()
        {
            ship.Stop();
            hud.Visible = false;
            gameOver.Start();
            PlayList.Stop();

            gameScore.Lives--;
            gameScore.LevelPosition = MathHelper.Clamp(gameScore.LevelPosition + asteroidField.LevelPosition, 0.0f, 1.0f);
        }

        private void Victory()
        {
            ship.Stop();
            hud.Visible = false;
            victory.Start();
            PlayList.Stop();

            gameScore.Score += (int)(ship.Health * 500);
            gameScore.Score += (int)(ship.Fuel * 500);
        }

        #endregion

        #region Update

        /// <summary>
        /// Called when the Screen needs to be updated.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Update(GameTime gameTime)
        {
            if (toVisible)
            {
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toVisible = false; trTime = 0.0f; Paused = false; InputEnabled = true; vibration.Resume(); sound.PlayAllSounds(); }
                else { InputEnabled = false; }
            }

            if (InputEnabled)
            {
                if (PlayerInput.IsPauseGame(PlayerIndex))
                {
                    if (state == GAMESTATE.GAMEOVER)
                        return;

                    Paused = true;
                    ScreenSound.Pause();
                    ScreenManager.AddScreen(new PauseMenuScreen(ScreenManager));
                }
            }

            if (!Paused)
            {
                Update_Gameplay(gameTime);
            }

            Update_HeadUpDisplay();
            Update_PostProcessing();

            base.Update(gameTime);
        }

        #region Update_Gameplay

        private void Update_Gameplay(GameTime gameTime)
        {
            switch (state)
            {
                case GAMESTATE.GAMEPLAY:
                    {
                        gameScore.PlayTime += gameTime.ElapsedGameTime;
                        whoshCnt++;
                        velCnt++;
                        float levelPosition = MathHelper.Clamp(gameScore.LevelPosition + asteroidField.LevelPosition, 0.0f, 1.0f);

                        if (levelPosition == 1.0f)
                        {
                            state = GAMESTATE.GAMEOVER;
                            Victory();
                        }
                        else if (ship.Health == 0.0f)
                        {
                            state = GAMESTATE.GAMEOVER;
                            LifeLost();
                        }
                        else if (ship.Health <= 0.30f)
                        {
                            warning.LowHealth(ship.Health);
                            vibration.Start(PlayerIndex, 0.25f, 0.25f, TimeSpan.FromMilliseconds(1000));
                        }
                        else if (ship.Fuel == 0.0f)
                        {
                            warning.OutFuel();
                        }

                        // % 30 => twice per second
                        if (velCnt % 30 == 0)
                        {
                            gameScore.Score += (int)Math.Round(10 * ship.Velocity, 0);
                            velCnt = 0;
                        }

                        break;
                    }
                default:
                    {
                        asteroidField.KillNearbyAsteroids();
                        break;
                    }
            }

            // broken glass
            message.Damage(ship.Health);

            Update_LensFlare(gameTime);
        }

        #endregion

        #region Update_PostProcessing

        private void Update_PostProcessing()
        {
            #region Velocity

            if (ship.Velocity <= 0.5f)
            {
                postScreenProcessor.BlurFactor = 0.1f + 0.5f * ship.Velocity;
                postScreenProcessor.BloomThreshold = 0.3f + 0.2f * (1.0f - (float)Math.Pow(1.0f - ship.Velocity / 0.5f, 2));
                postScreenProcessor.BloomIntensity = 1.0f + 1.0f * (1.0f - (float)Math.Pow(ship.Velocity / 0.5f, 2));
                postScreenProcessor.BloomSaturation = 0.0f + 1.0f * (1.0f - (float)Math.Pow(1.0f - ship.Velocity / 0.5f, 2));
                postScreenProcessor.BaseSaturation = 1.0f + 1.0f * (float)Math.Pow(1.0f - ship.Velocity / 0.5f, 2);
            }
            else
            {
                postScreenProcessor.BlurFactor = 0.70f * ship.Velocity;
                postScreenProcessor.BloomThreshold = 0.3f + 0.2f * (1.0f - (float)Math.Pow((ship.Velocity - 0.5f) / 0.5f, 2));
                postScreenProcessor.BloomIntensity = 1.0f + 1.0f * (float)Math.Pow((ship.Velocity - 0.5f) / 0.5f, 2);
                postScreenProcessor.BloomSaturation = 1.0f + 1.0f * (float)Math.Pow((ship.Velocity - 0.5f) / 0.5f, 2);
                postScreenProcessor.BaseSaturation = 0.0f + 1.0f * (1.0f - (float)Math.Pow((ship.Velocity - 0.5f) / 0.5f, 2));
            }

            #endregion

            #region Health

            if (ship.Health <= 0.10f)
            {
                postScreenProcessor.Color = new Color(0.50f, 0.0f, 0.0f);
                postScreenProcessor.BloomSaturation *= 0.125f;
                postScreenProcessor.BaseSaturation *= 0.125f;
                postScreenProcessor.BloomThreshold *= 0.125f;
            }
            else if (ship.Health <= 0.30f)
            {
                postScreenProcessor.Color = new Color(0.50f - 1.5f * (ship.Health - 0.10f), 0.0f, 0.0f);
                postScreenProcessor.BloomSaturation *= 0.125f + 1.875f * (ship.Health - 0.10f);
                postScreenProcessor.BaseSaturation *= 0.125f + 1.875f * (ship.Health - 0.10f);
                postScreenProcessor.BloomThreshold *= 0.125f + 1.875f * (ship.Health - 0.10f);
            }
            else
            {
                postScreenProcessor.Color = new Color(0.0f, 0.0f, 0.0f);

            }

            #endregion
        }

        #endregion

        #endregion
    }
}
